#pragma once

#include "../Threading/Thread.h"
#include "../Delegate/Delegate.h"
#include "../Threading/WaitHandle.h"
#include "../Threading/Lock.h"

#include <deque>
using std::deque;

namespace xgu{

class IAsyncResult;
class MethodInvoker;

class Invokable
{
public:
	Invokable();
	virtual ~Invokable();

	void BeginInvoke(const Delegate<void>& delegate)
		{ BeginInvoke(delegate, NULL); }
	void BeginInvoke(const Delegate<void>& delegate, IAsyncResult** out_async_result);

	void* EndInvoke(IAsyncResult& asyncResult);

	void Invoke(const Delegate<void>& delegate);

	bool InvokeRequired() const
	{
		return Thread::getTid() != tid_;
	}

	static void DoEvents();

protected:
	friend class MethodInvoker;
	void Remove(MethodInvoker& mi);

	friend class InvocationList;
	void DoInvocations();

private:
	Lock milist_lock_;
	deque<MethodInvoker*> mi_list_;
	const Thread::TID tid_;
};

}
